/*================================================================================
*
*
*                                   
*
*
* 项目名称: mcp2515-spi-can-demo
* 文件名称: LCD.c
* 创建日期: 21-01-15
* 文件描述: ILI9341 LCD 驱动及应用,应为字符宽高固定为8x16
*
================================================================================*/
#include "fsmc.h"
#include "gpio.h"
#include "fonts.h"
#include "DBG_PR.h"

#include "LCD.h"

uint8_t ucXPT2046_TouchFlag;
stType_XPT2046_TouchPara strXPT2046_TouchPara[] = {
   -0.006464,   -0.073259,  280.358032,    0.074878,    0.002052,   -6.545977,//扫描方式0
    0.086314,    0.001891,  -12.836658,   -0.003722,   -0.065799,  254.715714,//扫描方式1
    0.002782,    0.061522,  -11.595689,    0.083393,    0.005159,  -15.650089,//扫描方式2
    0.089743,   -0.000289,  -20.612209,   -0.001374,    0.064451,  -16.054003,//扫描方式3
    0.000767,   -0.068258,  250.891769,   -0.085559,   -0.000195,  334.747650,//扫描方式4
   -0.084744,    0.000047,  323.163147,   -0.002109,   -0.066371,  260.985809,//扫描方式5
   -0.001848,    0.066984,  -12.807136,   -0.084858,   -0.000805,  333.395386,//扫描方式6
   -0.085470,   -0.000876,  334.023163,   -0.003390,    0.064725,   -6.211169,//扫描方式7
};

uint8_t LCD_SCAN_MODE_ = 3;
typedef enum
{
    XPT2046_STATE_RELEASE,
    XPT2046_STATE_WAITING,
    XPT2046_STATE_PRESS,
}
enumTouchState;

//-private code------------------------------------------------------------------
static void s_ILI9341OpenWindow(uint16_t u16X, uint16_t u16Y, uint16_t u16Width, uint16_t u16Height);
static void s_ILI9341FillColor(uint32_t u32AmoutPoint, uint16_t u16RGB);
static void s_ILI9341FillPoint(uint16_t u16X, uint16_t u16Y, uint16_t u16RGB);
static void XPT2046WrCmd(uint8_t u8Cmd);
static uint16_t XPT2046RdCmd(void);
static uint16_t XPT2046RdAdc(uint8_t u8ChCmd);
static void XPT2046_DelayUS(__IO uint32_t ulCount);
static void XPT2046_ReadAdc_XY(int16_t* sX_Ad, int16_t* sY_Ad);
static uint8_t XPT2046_ReadAdc_Smooth_XY(stType_XPT2046_Coordinate* pScreenCoordinate);

//-private data------------------------------------------------------------------

//-public data-------------------------------------------------------------------

#define ILI9341_CMD_ADR             ( (uint32_t)0x60000000 )
#define ILI9341_DATA_ADR            ( (uint32_t)(0x60000000+0x20000) )
//-Leval 1 Command-------------------------------
#define CMD_NOP                     (0x00)
#define CMD_SW_RST                  (0x01)
#define CMD_RD_ID_INFO              (0x04)
#define CMD_RD_DISP_STAT            (0x09)
#define CMD_RD_DISP_PWR_MOD         (0x0A)
#define CMD_RD_DISP_MADCTL          (0x0B)
#define CMD_RD_DISP_PX_FMT          (0x0C)
#define CMD_RD_DISP_IMG_FMT         (0x0D)
#define CMD_RD_DISP_SIG_MOD         (0x0E)
#define CMD_RD_DISP_SD_RES          (0x0F)
#define CMD_ENTER_SLEEP             (0x10)
#define CMD_SLEEP_OUT               (0x11)
#define CMD_PARTIAL_MOD_ON          (0x12)
#define CMD_NORMAL_DISP_ON          (0x13)
#define CMD_DISP_INVERS_ON          (0x20)
#define CMD_DISP_INVERS_OFF         (0x21)
#define CMD_GAMMA_SET               (0x26)
#define CMD_DISP_OFF                (0x28)
#define CMD_DISP_ON                 (0x29)
#define CMD_COLUM_ADR_SET           (0x2A)
#define CMD_PAGE_ADR_SET            (0x2B)
#define CMD_MEM_WRITE               (0x2C)
#define CMD_COLOR_SET               (0x2D)
#define CMD_MEM_RD                  (0x2E)
#define CMD_PARTIAL_AREA            (0x30)
#define CMD_VERT_SCROL_DEF          (0x33)
#define CMD_TEAR_EFF_LINE_OFF       (0x34)
#define CMD_TEAR_EFF_LINE_ON        (0x35)
#define CMD_MEM_ACC_CTRL            (0x36)
#define CMD_VERT_SCROL_STA_ADR      (0x37)
#define CMD_IDLE_MOD_OFF            (0x38)
#define CMD_IDLE_MOD_ON             (0x39)
#define CMD_PIX_FMT_SET             (0x3A)
#define CMD_WR_MEM_CONTIN           (0x3C)
#define CMD_RD_MEM_CONTIN           (0x3D)
#define CMD_SET_TEAR_SL             (0x44) //Set Tear Scanline
#define CMD_SET_SL                  (0x45) //Get Scanline
#define CMD_WR_DISP_BRIGHT          (0x51)
#define CMD_WR_CTRL_DISP            (0x53)
#define CMD_RD_CTRL_DISP            (0x54)
#define CMD_WR_CABC                 (0x55) //Write Content Adaptive Brightness Control
#define CMD_RD_CABC                 (0x56) //Read Content Adaptive Brightness Control
#define CMD_WR_CABC_MIN_BRI         (0x5E)
#define CMD_RD_CABC_MIN_BRI         (0x5F)
#define CMD_RD_ID1                  (0xDA)
#define CMD_RD_ID2                  (0xDB)
#define CMD_RD_ID3                  (0xDC)
//-Level 2 Command-------------------------------
#define CMD_RGB_ISC                 (0xB0) //RGB Interface Control
#define CMD_FRAME_RATE_CTRL1        (0xB1) //Frame Rate Control(In Normal Mode/Full Colors)
#define CMD_FRAME_RATE_CTRL2        (0xB2) //Frame Rate Control(In Idle Mode/8 colors)
#define CMD_FRAME_RATE_CTRL3        (0xB3) //Frame Rate Control(In Partial Mode/Full Colors)
#define CMD_DISP_INV_CTRL           (0xB4)
#define CMD_BLK_PCH_CTRL            (0xB5)
#define CMD_DISP_FUNC_CTRL          (0xB6)
#define CMD_ENT_MOD_SET             (0xB7)
#define CMD_BKL_CTRL1               (0xB8)
#define CMD_BKL_CTRL2               (0xB9)
#define CMD_BKL_CTRL3               (0xBA)
#define CMD_BKL_CTRL4               (0xBB)
#define CMD_BKL_CTRL5               (0xBC)
#define CMD_BKL_CTRL7               (0xBE)
#define CMD_BKL_CTRL8               (0xBF)
#define CMD_PWR_CTRL1               (0xC0)
#define CMD_PWR_CTRL2               (0xC1)
#define CMD_VCOM_CTRL1              (0xC5)
#define CMD_VCOM_CTRL2              (0xC7)
#define CMD_NV_MEM_WR               (0xD0)
#define CMD_NV_MEM_KEY              (0xD1)
#define CMD_NV_MEM_STAT             (0xD2)
#define CMD_RD_ID4                  (0xD3)
#define CMD_P_GAM_COR               (0xE0) //Positive Gamma Correction
#define CMD_N_GAM_COR               (0xE1) //Negative Gamma Correction
#define CMD_DIG_GAM_CTRL1           (0xE2)
#define CMD_DIG_GAM_CTRL2           (0xE3)
#define CMD_INTF_CTRL               (0xF6)
//-Extend register command-----------------------
#define CMD_PWR_CTRLA               (0xCB)
#define CMD_PWR_CTRLB               (0xCF)
#define CMD_DRV_TIM_CTRLA           (0xE8)
#define CMD_DRV_TIM_CTRLB           (0xEA)
#define CMD_PWRON_SEQ_CTRL          (0xED)
#define CMD_EN_3_GAM                (0xF2)
#define CMD_PUMP_RATIO              (0xF7)

//-XPT2046 definitions---------------------------
#define XPT2046_CLK_HI()            HAL_GPIO_WritePin(TP_CLK_GPIO_Port, TP_CLK_Pin, GPIO_PIN_SET)
#define XPT2046_CLK_LO()            HAL_GPIO_WritePin(TP_CLK_GPIO_Port, TP_CLK_Pin, GPIO_PIN_RESET)
#define XPT2046_MOSI_1()            HAL_GPIO_WritePin(TP_DI_GPIO_Port, TP_DI_Pin, GPIO_PIN_SET)
#define XPT2046_MOSI_0()            HAL_GPIO_WritePin(TP_DI_GPIO_Port, TP_DI_Pin, GPIO_PIN_RESET)
#define XPT2046_MISO()              HAL_GPIO_ReadPin(TP_DO_GPIO_Port, TP_DO_Pin)
#define XPT2046_DELAY()             for(uint8_t i=0; i<=5; i++)
#define XPT2046_CHANNEL_X           (0x90)
#define XPT2046_CHANNEL_Y           (0xD0)
#define XPT2046_PENIRQ_ActiveLevel  0
#define XPT2046_PENIRQ_Read()       HAL_GPIO_ReadPin(TP_IRQ_GPIO_Port, TP_IRQ_Pin)
#define DURIATION_TIME              2               //消抖时间

/********************************************************************************
*函数功能: 
    内联函数,向屏幕写命令
*修改记录: 
*日期:                作者:                摘要:
      21-01-15             YummoShin            Create
********************************************************************************/
static inline void ILI9341_WR_CMD(uint16_t u16Cmd)
{
    *(uint16_t *)ILI9341_CMD_ADR = u16Cmd;
}

/********************************************************************************
*函数功能: 
    内联函数,屏幕写数据
*修改记录: 
*日期:                作者:                摘要:
      21-01-15             YummoShin            Create
********************************************************************************/
static inline void ILI9341_WR_DATA(uint16_t u16Data)
{
    *(uint16_t *)ILI9341_DATA_ADR = u16Data;
}

/********************************************************************************
*函数功能: 
    ILI9341屏幕初始化命令
*修改记录: 
*日期:                作者:                摘要:
      21-01-17                                 Create
********************************************************************************/
void InitLcd(void)
{
    HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_RESET);
    HAL_Delay(50);
    HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_SET);
    HAL_Delay(50);

    ILI9341_WR_CMD(CMD_PWR_CTRLB);
    ILI9341_WR_DATA(0x00);
    ILI9341_WR_DATA(0x81);
    ILI9341_WR_DATA(0x30);

    ILI9341_WR_CMD(CMD_PWRON_SEQ_CTRL);
    ILI9341_WR_DATA(0x64);
    ILI9341_WR_DATA(0x03);
    ILI9341_WR_DATA(0x12);
    ILI9341_WR_DATA(0X81);

    ILI9341_WR_CMD(CMD_DRV_TIM_CTRLA);
    ILI9341_WR_DATA(0x85);
    ILI9341_WR_DATA(0x10);
    ILI9341_WR_DATA(0x78);

    ILI9341_WR_CMD(CMD_DRV_TIM_CTRLB);
    ILI9341_WR_DATA(0x00);
    ILI9341_WR_DATA(0x00);

    ILI9341_WR_CMD(CMD_PWR_CTRLA);
    ILI9341_WR_DATA(0x39);
    ILI9341_WR_DATA(0x2C);
    ILI9341_WR_DATA(0x00);
    ILI9341_WR_DATA(0x34);
    ILI9341_WR_DATA(0x02);

    ILI9341_WR_CMD(CMD_PUMP_RATIO);
    ILI9341_WR_DATA(0xF7);
    ILI9341_WR_DATA(0x20);

    ILI9341_WR_CMD(CMD_FRAME_RATE_CTRL1);
    ILI9341_WR_DATA(0x00);
    ILI9341_WR_DATA(0x10);

    ILI9341_WR_CMD(CMD_DISP_FUNC_CTRL);
    ILI9341_WR_DATA(0x8A);
    ILI9341_WR_DATA(0xA2);

    ILI9341_WR_CMD(CMD_PWR_CTRL1);
    ILI9341_WR_DATA(0x35);

    ILI9341_WR_CMD(CMD_PWR_CTRL2);
    ILI9341_WR_DATA(0x11);

    ILI9341_WR_CMD(CMD_VCOM_CTRL1);
    ILI9341_WR_DATA(0x45);
    ILI9341_WR_DATA(0x45);

    ILI9341_WR_CMD(CMD_VCOM_CTRL2);
    ILI9341_WR_DATA(0xA2);

    ILI9341_WR_CMD(CMD_EN_3_GAM);
    ILI9341_WR_DATA(0x00);

    ILI9341_WR_CMD(CMD_GAMMA_SET);
    ILI9341_WR_DATA(0x01);

    ILI9341_WR_CMD(CMD_P_GAM_COR);
    ILI9341_WR_DATA(0x0F);
    ILI9341_WR_DATA(0x26);
    ILI9341_WR_DATA(0x24);
    ILI9341_WR_DATA(0x0B);
    ILI9341_WR_DATA(0x0E);
    ILI9341_WR_DATA(0x09);
    ILI9341_WR_DATA(0x54);
    ILI9341_WR_DATA(0xA8);
    ILI9341_WR_DATA(0x46);
    ILI9341_WR_DATA(0x0C);
    ILI9341_WR_DATA(0x17);
    ILI9341_WR_DATA(0x09);
    ILI9341_WR_DATA(0x0F);
    ILI9341_WR_DATA(0x07);
    ILI9341_WR_DATA(0x00);

    ILI9341_WR_CMD(CMD_N_GAM_COR);
    ILI9341_WR_DATA(0x00);
    ILI9341_WR_DATA(0x19);
    ILI9341_WR_DATA(0x1B);
    ILI9341_WR_DATA(0x04);
    ILI9341_WR_DATA(0x10);
    ILI9341_WR_DATA(0x07);
    ILI9341_WR_DATA(0x2A);
    ILI9341_WR_DATA(0x47);
    ILI9341_WR_DATA(0x39);
    ILI9341_WR_DATA(0x03);
    ILI9341_WR_DATA(0x06);
    ILI9341_WR_DATA(0x06);
    ILI9341_WR_DATA(0x30);
    ILI9341_WR_DATA(0x38);
    ILI9341_WR_DATA(0x0F);

    ILI9341_WR_CMD(CMD_MEM_ACC_CTRL);
    ILI9341_WR_DATA(0x68);

    ILI9341_WR_CMD(CMD_COLUM_ADR_SET);
    ILI9341_WR_DATA(0x00);
    ILI9341_WR_DATA(0x00);
    ILI9341_WR_DATA(0x00);
    ILI9341_WR_DATA(0xEF);

    ILI9341_WR_CMD(CMD_PAGE_ADR_SET);
    ILI9341_WR_DATA(0x00);
    ILI9341_WR_DATA(0x00);
    ILI9341_WR_DATA(0x01);
    ILI9341_WR_DATA(0x3F);

    ILI9341_WR_CMD(CMD_PIX_FMT_SET);
    ILI9341_WR_DATA(0x55);

    ILI9341_WR_CMD(CMD_SLEEP_OUT);

    HAL_Delay(100);

    HAL_GPIO_WritePin(LCD_BL_GPIO_Port, LCD_BL_Pin, GPIO_PIN_RESET);
    ILI9341_WR_CMD(CMD_DISP_ON);
}

/********************************************************************************
*函数功能: 
    LCD屏幕背光控制
    @param u8State, 1亮 0灭
*修改记录: 
*日期:                作者:                摘要:
      21-01-17             YummoShin            Create
********************************************************************************/
void LcdBlCtrl(uint8_t u8State)
{
    HAL_GPIO_WritePin(LCD_BL_GPIO_Port, LCD_BL_Pin, u8State);
}

/********************************************************************************
*函数功能: 
    开窗
    @param u16X, 开窗锚点坐标X
    @param u16Y, 开窗锚点坐标Y
    @param u16Width, 窗口宽
    @param u16Height, 窗口高
*修改记录: 
*日期:                作者:                摘要:
      21-01-21                                 Create
********************************************************************************/
static void s_ILI9341OpenWindow(uint16_t u16X, uint16_t u16Y, uint16_t u16Width, uint16_t u16Height)
{
    ILI9341_WR_CMD(CMD_COLUM_ADR_SET);
    ILI9341_WR_DATA(u16X>>8);
    ILI9341_WR_DATA(u16X&0xFF);
    ILI9341_WR_DATA((u16X+u16Width-1)>>8);
    ILI9341_WR_DATA((u16X+u16Width-1)&0xFF);

    ILI9341_WR_CMD(CMD_PAGE_ADR_SET);
    ILI9341_WR_DATA(u16Y>>8);
    ILI9341_WR_DATA(u16Y&0xFF);
    ILI9341_WR_DATA((u16Y+u16Height-1)>>8);
    ILI9341_WR_DATA((u16Y+u16Height)&0xFF);
}

/********************************************************************************
*函数功能: 
    填充像素颜色
    @param u32AmoutPoint, 像素数量
    @param u16RGB, 颜色
*修改记录: 
*日期:                作者:                摘要:
      21-01-21             YummoShin            Create
********************************************************************************/
static void s_ILI9341FillColor(uint32_t u32AmoutPoint, uint16_t u16RGB)
{
    uint32_t i;

    ILI9341_WR_CMD(CMD_MEM_WRITE);
    for(i=0; i<u32AmoutPoint; i++)
        ILI9341_WR_DATA(u16RGB);
}

/********************************************************************************
*函数功能: 
    打点函数
    @param u16X, cordinate X
    @param u16Y, cordinate Y
    @param u16RGB, the RGB565 color data
*修改记录: 
*日期:                作者:                摘要:
      21-01-21             YummoShin            Create
********************************************************************************/
static void s_ILI9341FillPoint(uint16_t u16X, uint16_t u16Y, uint16_t u16RGB)
{
    s_ILI9341OpenWindow(u16X, u16Y, 1, 1);
    s_ILI9341FillColor(1, u16RGB);
}

/********************************************************************************
*函数功能: 
    绘制色块,色块中心位置显示字符串
    @param pColBk, color block对象指针
*修改记录: 
*日期:                作者:                摘要:
      21-01-28             YummoShin            Create
********************************************************************************/
void LcdDrawColorBlock(const ColorBlock_t *pColBk)
{
    uint16_t u16StrWidth=0;
    uint16_t i=0, j=0;
    uint8_t u8RowMod=0, u8Mask=0;

    s_ILI9341OpenWindow(pColBk->u16X, pColBk->u16Y, pColBk->u16Width, pColBk->u16Height);
    s_ILI9341FillColor(pColBk->u16Width*pColBk->u16Height, pColBk->u16RGB);

    if(pColBk->pStr!=NULL)
    {
        for(i=0; (pColBk->pStr)[i]!='\0'; i++);

        u16StrWidth = 8*i;

        s_ILI9341OpenWindow( ((pColBk->u16Width-u16StrWidth)/2+pColBk->u16X), 
                             ((pColBk->u16Height-12)/2+pColBk->u16Y),
                             u16StrWidth,
                             12 );
        
        ILI9341_WR_CMD(CMD_MEM_WRITE);
        for(i=0; i<12; i++) //
        {
            for(j=0; j<u16StrWidth; j++)
            {
                u8RowMod = (Font12.table)[((pColBk->pStr)[j/8]-32)*12+i];
                
                u8Mask = 0x80>>(j%8);

                if(u8RowMod&u8Mask)
                {
                    ILI9341_WR_DATA(~(pColBk->u16RGB));
                }
                else
                {
                    ILI9341_WR_DATA(pColBk->u16RGB);
                }
            }
        }
    }
}

/********************************************************************************
*函数功能: 
    绘制拖动动作条,按钮可显示颜色固定长高,长:276,高:20,按钮20*20
    @param u16X, 动作条锚点X
    @param u16Y, 动作条锚点Y
    @param u16Val, 按钮值
    @param u16Z, 按钮颜色
*修改记录: 
*日期:                作者:                摘要:
      21-01-28             YummoShin            Create
********************************************************************************/
void LcdDrawColorBar(uint16_t u16X, uint16_t u16Y, uint8_t u8Val, uint16_t u16RGB)
{
    uint16_t i=0;

    //绘制背景
    s_ILI9341OpenWindow(u16X, u16Y, 276, 20);
    s_ILI9341FillColor(276*20, WHITE); //背景为白色
    //绘制量程条
    s_ILI9341OpenWindow(u16X, u16Y+5, 276, 10);
    ILI9341_WR_CMD(CMD_MEM_WRITE);
    for(i=0; i<2760; i++)
    {
        if((i%276)>=u8Val && (i%276)<(u8Val+20))
        {
            ILI9341_WR_DATA(WHITE);
        }
        else if(
            (i<276)         ||
            (i%276==0)      ||
            (i%276==275)    ||
            (i>276*9)
        ){
            ILI9341_WR_DATA(BLACK);
        }
        else
        {
            ILI9341_WR_DATA(LGRAY);
        }
    }
    //绘制按钮
    s_ILI9341OpenWindow(u16X+u8Val, u16Y, 20, 20);
    ILI9341_WR_CMD(CMD_MEM_WRITE);
    for(i=0; i<400; i++)
    {
        if(
            (i<20)          ||
            (i%20==0)       ||
            (i%20==19)      ||
            (i>380)
        ){
            ILI9341_WR_DATA(BLACK);
        }
        else
        {
            ILI9341_WR_DATA(u16RGB);
        }        
    }
}

/*******************************************************************************
*函数名称 : 
*返回参数 : 
*函数功能 : 
*作者 :               日期 :                    摘要 :
*      Yummo                2019-10-11                创建
*******************************************************************************/
static void XPT2046_DelayUS(__IO uint32_t ulCount)
{
    uint32_t i, uc;
    for(i=0; i<ulCount; i--)
	{
        uc = 12;
        while(uc--);
    }
}

/********************************************************************************
*函数功能: 
    模拟SPI功能向XPT2046发送命令
    @param u8Cmd, 控制命令
*修改记录: 
*日期:                作者:                摘要:
      21-01-30                                 Create
********************************************************************************/
static void XPT2046WrCmd(uint8_t u8Cmd)
{
    uint8_t i=0;

    XPT2046_MOSI_0();
    XPT2046_CLK_LO();

    for(i=0; i<8; i++)
    {
        u8Cmd&(0x80>>i) ? XPT2046_MOSI_1() : XPT2046_MOSI_0();
        XPT2046_DELAY();
        XPT2046_CLK_HI();
        XPT2046_DELAY();
        XPT2046_CLK_LO();
    }
}

/********************************************************************************
*函数功能: 
    模拟SPI读取从机数据
    @retval u16Buf, 获取的SPI从机数据
*修改记录: 
*日期:                作者:                摘要:
      21-01-30                                 Create
********************************************************************************/
static uint16_t XPT2046RdCmd(void)
{
    uint8_t i;
    uint16_t u16Buf=0, u16Tmp;

    XPT2046_MOSI_0();
    XPT2046_CLK_HI();

    for(i=0; i<12; i++)
    {
        XPT2046_CLK_LO();
        u16Tmp = XPT2046_MISO();
        u16Buf |= u16Tmp<<(11-i);
        XPT2046_CLK_HI();
    }

    return u16Buf;
}

/********************************************************************************
*函数功能: 
    读取XPT2046触摸ADC原始数据
    @param u8ChCmd, 通道参数命令
        @arg XPT2046_CHANNEL_X
        @arg XPT2046_CHANNEL_Y
    @retval 根据输入参数返回触摸ADC原始数据
*修改记录: 
*日期:                作者:                摘要:
      21-01-31                                 Create
********************************************************************************/
static uint16_t XPT2046RdAdc(uint8_t u8ChCmd)
{
    XPT2046WrCmd(u8ChCmd);
    return XPT2046RdCmd();
}

/*******************************************************************************
*函数名称 : static void XPT2046_ReadAdc_XY(int16_t* sX_Ad, int16_t* sY_Ad)
*返回参数 : void
*函数功能 : 获取坐标
*@param sX_Ad x轴ADC值的指针
*@param sY_Ad y轴ADC值的指针
*作者 :               日期 :                    摘要 :
*                           2019-10-13                创建
*******************************************************************************/
static void XPT2046_ReadAdc_XY(int16_t* sX_Ad, int16_t* sY_Ad)
{
    int16_t sX_Ad_Temp, sY_Ad_Temp;

    sX_Ad_Temp = XPT2046RdAdc(XPT2046_CHANNEL_X);
    XPT2046_DelayUS(1);
    sY_Ad_Temp = XPT2046RdAdc(XPT2046_CHANNEL_Y);

    *sX_Ad = sX_Ad_Temp;
    *sY_Ad = sY_Ad_Temp;
}

/*******************************************************************************
*函数名称 : static uint8_t XPT2046_ReadAdc_Smooth_XY(stType_XPT2046_Coordinate* pScreenCoordinate)
*返回参数 : 坐标采集成功标志
*函数功能 : 坐标采集滤波
*作者 :               日期 :                    摘要 :
*                           2019-10-13                创建
*******************************************************************************/
static uint8_t XPT2046_ReadAdc_Smooth_XY(stType_XPT2046_Coordinate* pScreenCoordinate)
{
    uint8_t ucCount = 0;
    uint8_t i;
    int16_t sAD_X, sAD_Y;
    int16_t sBufferArray[2][10] = {{0}, {0}};
    int16_t lX_Min, lX_Max, lY_Min, lY_Max;
    int32_t i32Tmp;

    do
    {
        XPT2046_ReadAdc_XY(&sAD_X, &sAD_Y);
        sBufferArray[0][ucCount] = sAD_X;
        sBufferArray[1][ucCount] = sAD_Y;
        ucCount++;
    }while( (XPT2046_PENIRQ_Read()==XPT2046_PENIRQ_ActiveLevel) && (ucCount<10) );

    if( (XPT2046_PENIRQ_Read()!=XPT2046_PENIRQ_ActiveLevel) )
        ucXPT2046_TouchFlag = 0;
    
    if(ucCount==10)
    {
        lX_Max = lX_Min = sBufferArray[0][0];
        lY_Max = lY_Min = sBufferArray[1][0];
        
        for(i=0, i32Tmp=0; i<10; i++)
        {
            if(sBufferArray[0][i]<lX_Min)
                lX_Min = sBufferArray[0][i];
            else if(sBufferArray[0][i]>lX_Max)
                lX_Max = sBufferArray[0][i];
            
            i32Tmp += sBufferArray[0][i];
        }
        pScreenCoordinate->x = (i32Tmp-lX_Min-lX_Max)>>3;

        for(i=0, i32Tmp=0; i<10; i++)
        {
            if(sBufferArray[1][i]<lY_Min)
                lY_Min = sBufferArray[1][i];
            else if(sBufferArray[1][i]>lY_Max)
                lY_Max = sBufferArray[1][i];
            i32Tmp += sBufferArray[1][i];
        }
        pScreenCoordinate->y = (i32Tmp-lY_Min-lY_Max)>>3;

        return 1;
    }

    return 0;
}

/*******************************************************************************
*函数名称 : 
*返回参数 : 
*函数功能 : 
*作者 :               日期 :                    摘要 :
*                           2019-10-13                创建
*******************************************************************************/
uint8_t XPT2046_Get_TouchedPoint(stType_XPT2046_Coordinate* pDisplayCoordinate,
                                 stType_XPT2046_TouchPara* pTouchPar)
{
    uint8_t ucRet = 1;
    stType_XPT2046_Coordinate stScreenCoordinate;

    if(XPT2046_ReadAdc_Smooth_XY(&stScreenCoordinate))
    {
        pDisplayCoordinate->x = pTouchPar[LCD_SCAN_MODE_].dX_X*stScreenCoordinate.x + pTouchPar[LCD_SCAN_MODE_].dX_Y*stScreenCoordinate.y + pTouchPar[LCD_SCAN_MODE_].dX;
        pDisplayCoordinate->y = pTouchPar[LCD_SCAN_MODE_].dY_X*stScreenCoordinate.x + pTouchPar[LCD_SCAN_MODE_].dY_Y*stScreenCoordinate.y + pTouchPar[LCD_SCAN_MODE_].dY;
    }
    else 
        ucRet = 0;
    
    return ucRet;
}

/*******************************************************************************
*函数名称 : uint8_t XPT2046_TouchDetect(void)
*返回参数 : @param detectResult :屏幕是否按下的状态
*函数功能 : 检测按键值
*作者 :               日期 :                    摘要 :
*                          2019-10-13                创建
*******************************************************************************/
uint8_t XPT2046_TouchDetect(void)
{
    static enumTouchState touch_state = XPT2046_STATE_RELEASE;
    static uint32_t i;

    uint8_t detectResult = TOUCH_NOT_PRESS;

    switch(touch_state)
    {
    case XPT2046_STATE_RELEASE:
        if(XPT2046_PENIRQ_Read()==XPT2046_PENIRQ_ActiveLevel)
        {
            touch_state = XPT2046_STATE_WAITING;
            detectResult = TOUCH_NOT_PRESS;
        }
        else 
        {
            touch_state = XPT2046_STATE_RELEASE;
            detectResult = TOUCH_NOT_PRESS;
        }
        break;
    
    case XPT2046_STATE_WAITING:
        if(XPT2046_PENIRQ_Read()==XPT2046_PENIRQ_ActiveLevel)
        {
            i++;
            if(i>DURIATION_TIME)
            {
                i = 0;
                touch_state = XPT2046_STATE_PRESS;
                detectResult = TOUCH_PRESSED;
            }
            else
            {
                touch_state = XPT2046_STATE_WAITING;
                detectResult = TOUCH_NOT_PRESS;
            }
        }
        else
        {
            i = 0;
            touch_state = XPT2046_STATE_RELEASE;
            detectResult = TOUCH_NOT_PRESS;
        }
        break;

    case XPT2046_STATE_PRESS:
        if(XPT2046_PENIRQ_Read()==XPT2046_PENIRQ_ActiveLevel)
        {
            touch_state = XPT2046_STATE_PRESS;
            detectResult = TOUCH_PRESSED;
        }
        else
        {
            touch_state = XPT2046_STATE_RELEASE;
            detectResult = TOUCH_NOT_PRESS;
        }
        break;

    default :
        touch_state = XPT2046_STATE_RELEASE;
        detectResult = TOUCH_NOT_PRESS;
        break;
    }

    return detectResult;
}

/*******************************************************************************
*函数名称 : 
*返回参数 : 
*函数功能 : 
*作者 :               日期 :                    摘要 :
*                           2019-10-13                创建
*******************************************************************************/
void XPT2046_TouchEventHandler(void)
{
    static stType_XPT2046_Coordinate cinfo = {-1, -1, -1, -1};
    if(XPT2046_TouchDetect()==TOUCH_PRESSED)
    {
        XPT2046_Get_TouchedPoint(&cinfo, strXPT2046_TouchPara);
        cinfo.pre_x = cinfo.x;
        cinfo.pre_y = cinfo.y;

        DBG_PR("LCD coordinate: x: %d, y: %d\n", cinfo.x, cinfo.y);
    }
    else 
    {
        cinfo.x = cinfo.pre_x = -1;
        cinfo.y = cinfo.pre_y = -1;
    }
}
